/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

#include "StdAfx.h"
#include ".\MUtilsSO.h"

//---------------------------------------------------------------------------
#define BUFSIZE 80
//---------------------------------------------------------------------------
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
//---------------------------------------------------------------------------

MUtilsSO::MUtilsSO(void)
{
}

MUtilsSO::~MUtilsSO(void)
{
}

//---------------------------------------------------------------------------

CString MUtilsSO::GetOSFullName(void)
{
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
HKEY hKey;
TCHAR szProductType[BUFSIZE];
DWORD dwBufLen;
LONG lRet;
CString str, sss;

	dwBufLen = BUFSIZE;
	str.Empty();

	// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
	// If that fails, try using the OSVERSIONINFO structure.
	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
	bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
	if(!bOsVersionInfoEx){
		osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
		if(!GetVersionEx((OSVERSIONINFO *)&osvi))
			return str;
	}

	switch (osvi.dwPlatformId){
		// Test for the Windows NT product family.
		case VER_PLATFORM_WIN32_NT:
			// Test for the specific product family.
			if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2)
				str = "Windows Server 2003 family, ";
			if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==1)
				str = "Windows XP ";
			if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
				str = "Windows 2000 ";
			if(osvi.dwMajorVersion<=4)
				str = "Windows NT ";

			// Test for specific product on Windows NT 4.0 SP6 and later.
			if(bOsVersionInfoEx){
				// Test for the workstation type.
				if(osvi.wProductType==VER_NT_WORKSTATION){
					if(osvi.dwMajorVersion==4)
						str += "Workstation 4.0 ";
					else if(osvi.wSuiteMask & VER_SUITE_PERSONAL)
						str += "Home Edition ";
					else str += "Professional ";
				}
				// Test for the server type.
				else if(osvi.wProductType==VER_NT_SERVER){
					if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2){
						if(osvi.wSuiteMask & VER_SUITE_DATACENTER)
							str += "Datacenter Edition ";
						else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
							str += "Enterprise Edition ";
						else if(osvi.wSuiteMask==VER_SUITE_BLADE)
							str += "Web Edition ";
						else
							str += "Standard Edition ";
					}
					else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0){
						if(osvi.wSuiteMask & VER_SUITE_DATACENTER)
							str += "Datacenter Server ";
						else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
							str += "Advanced Server ";
						else
							str += "Server ";
					}
					else{  // Windows NT 4.0
						if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
							str += "Server 4.0, Enterprise Edition ";
						else
							str += "Server 4.0 ";
					}
				}
			}
			else{  // Test for specific product on Windows NT 4.0 SP5 and earlier
				lRet = RegOpenKeyEx(
						HKEY_LOCAL_MACHINE,
						_T("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
						0,
						KEY_QUERY_VALUE,
						&hKey);
				if(lRet!=ERROR_SUCCESS) return str;

				lRet = RegQueryValueEx(
						hKey,
						_T("ProductType"),
						NULL,
						NULL,
						(LPBYTE)szProductType,
						&dwBufLen);
				if((lRet!=ERROR_SUCCESS) || (dwBufLen>BUFSIZE)){
					RegCloseKey(hKey);
					return str;
				}

				RegCloseKey(hKey);

				if(lstrcmpi(szProductType, _T("WINNT"))   ==0) str += "Workstation ";
				if(lstrcmpi(szProductType, _T("LANMANNT"))==0) str += "Server ";
				if(lstrcmpi(szProductType, _T("SERVERNT"))==0) str += "Advanced Server ";

//				printf( "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion );
			}

			// Display service pack (if any) and build number.
			if(osvi.dwMajorVersion==4 && lstrcmpi(osvi.szCSDVersion, _T("Service Pack 6"))==0){
				// Test for SP6 versus SP6a.
				lRet=RegOpenKeyEx(
						HKEY_LOCAL_MACHINE,
						_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"),
						0,
						KEY_QUERY_VALUE,
						&hKey);
				if(lRet==ERROR_SUCCESS ){
					sss.Format(_T("Service Pack 6a (Build %d)"), osvi.dwBuildNumber & 0xFFFF);
					str += sss;
				}
				else{ // Windows NT 4.0 prior to SP6a
					sss.Format(_T("%s (Build %d)"), osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
					str += sss;
				}
				RegCloseKey( hKey );
			}
			else{ // Windows NT 3.51 and earlier or Windows 2000 and later
				sss.Format(_T("%s (Build %d)"), osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
				str += sss;
			}
		break;

		// Test for the Windows 95 product family.
		case VER_PLATFORM_WIN32_WINDOWS:
			if(osvi.dwMajorVersion==4 && osvi.dwMinorVersion==0){
				str += "Windows 95 ";
				if(osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
					str+="OSR2 ";
			}
			if(osvi.dwMajorVersion==4 && osvi.dwMinorVersion==10){
				str += "Windows 98 ";
				if(osvi.szCSDVersion[1]=='A')
					str+="SE ";
			}
			if(osvi.dwMajorVersion==4 && osvi.dwMinorVersion==90){
				str += "Windows Millennium Edition";
			}
			break;

		case VER_PLATFORM_WIN32s:
			str += "Microsoft Win32s";
			break;
	}

	return str;
}
//---------------------------------------------------------------------------

bool MUtilsSO::AtLeastWin2k(void)
{
OSVERSIONINFO osvi;

	osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
	if(!GetVersionEx(&osvi))
		return false;

	if(osvi.dwMajorVersion>=5) return true;
	return false;
}

//---------------------------------------------------------------------------

CString MUtilsSO::GetOSTypeName_6_0(DWORD typeIn)
{
	CString str;

#ifdef PRODUCT_ULTIMATE
	switch(typeIn){
		case PRODUCT_ULTIMATE:
			str = _T("Ultimate Edition");
			break;
		case PRODUCT_HOME_PREMIUM:
			str = _T("Home Premium Edition");
			break;
		case PRODUCT_HOME_BASIC:
			str = _T("Home Basic Edition");
			break;
		case PRODUCT_ENTERPRISE:
			str = _T("Enterprise Edition");
			break;
		case PRODUCT_BUSINESS:
			str = _T("Business Edition");
			break;
		case PRODUCT_STARTER:
			str = _T("Starter Edition");
			break;
		case PRODUCT_CLUSTER_SERVER:
			str = _T("Cluster Server Edition");
			break;
		case PRODUCT_DATACENTER_SERVER:
			str = _T("Datacenter Edition");
			break;
		case PRODUCT_DATACENTER_SERVER_CORE:
			str = _T("Datacenter Edition (core installation)");
			break;
		case PRODUCT_ENTERPRISE_SERVER:
			str = _T("Enterprise Edition");
			break;
		case PRODUCT_ENTERPRISE_SERVER_CORE:
			str = _T("Enterprise Edition (core installation)");
			break;
		case PRODUCT_ENTERPRISE_SERVER_IA64:
			str = _T("Enterprise Edition for Itanium-based Systems");
			break;
		case PRODUCT_SMALLBUSINESS_SERVER:
			str = _T("Small Business Server");
			break;
		case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
			str = _T("Small Business Server Premium Edition");
			break;
		case PRODUCT_STANDARD_SERVER:
			str = _T("Standard Edition");
			break;
		case PRODUCT_STANDARD_SERVER_CORE:
			str = _T("Standard Edition (core installation)");
			break;
		case PRODUCT_WEB_SERVER:
			str = _T("Web Server Edition");
			break;
		default:
			str.Empty();
	}
#else
	str.Empty();
#endif

	return str;
}

//---------------------------------------------------------------------------

CString MUtilsSO::GetOSFullNameEx(void)
{
	OSVERSIONINFOEX osvi;
	SYSTEM_INFO si;
	PGNSI pGNSI;
	PGPI pGPI;
	DWORD dwType;
	CString str;
	CString sss;

	ZeroMemory(&si, sizeof(SYSTEM_INFO));
	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));

	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
	if(!GetVersionEx((OSVERSIONINFO *)&osvi)){
		str = _T("-");
		return str;
	}

	// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.

	pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
	if(pGNSI!=NULL) pGNSI(&si);
	else            GetSystemInfo(&si);

	if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion>4){
		// str = _T("Microsoft ");
		str.Empty();

		// >>>>> Vista, 2008 <<<<<
		if(osvi.dwMajorVersion==6 && osvi.dwMinorVersion==0){
			if( osvi.wProductType == VER_NT_WORKSTATION ) str += _T("Windows Vista");
			else                                          str += _T("Windows Server 2008");

			pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
			pGPI(6, 0, 0, 0, &dwType);
			sss = GetOSTypeName_6_0(dwType);
			if(!sss.IsEmpty()){
				str += _T(" ");
				str += sss;
			}

			if(si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)     str += _T(" 64-bit");
			else
				if(si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL) str += _T(" 32-bit");
		}

	  // >>>>> 2003 <<<<<
	  if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2){
         if(GetSystemMetrics(SM_SERVERR2)) str += _T("Windows Server 2003 R2");
         else
			 if(osvi.wSuiteMask==VER_SUITE_STORAGE_SERVER) str += _T("Windows Storage Server 2003");
			 else
				 if(osvi.wProductType == VER_NT_WORKSTATION && si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
					  str += _T("Windows XP Professional x64 Edition");
				 else str += _T("Windows Server 2003");

         // Test for the server type.
		if(osvi.wProductType!=VER_NT_WORKSTATION){
			if(si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64){
                if(osvi.wSuiteMask & VER_SUITE_DATACENTER)      str += _T(" Datacenter Edition for Itanium-based Systems");
                else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) str += _T(" Enterprise Edition for Itanium-based Systems");
            }
            else if(si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64){
                if(osvi.wSuiteMask & VER_SUITE_DATACENTER)      str += _T(" Datacenter x64 Edition");
                else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) str += _T(" Enterprise x64 Edition");
                else                                            str += _T(" Standard x64 Edition");
            }
			else{
                if(osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)  str += _T(" Compute Cluster Edition");
                else if(osvi.wSuiteMask & VER_SUITE_DATACENTER) str += _T(" Datacenter Edition");
                else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) str += _T(" Enterprise Edition");
                else if(osvi.wSuiteMask & VER_SUITE_BLADE)      str += _T(" Web Edition");
                else                                            str += _T(" Standard Edition");
            }
         }
      }

	  // >>>>> XP <<<<<
	  if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==1){
         str += _T("Windows XP ");
         if(osvi.wSuiteMask & VER_SUITE_PERSONAL) str += _T("Home Edition");
         else                                     str += _T("Professional");
      }

	  // >>>>> 2000 <<<<<
	  if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0){
         str += _T("Windows 2000 ");

         if(osvi.wProductType==VER_NT_WORKSTATION)          str += _T("Professional");
		 else{
            if(osvi.wSuiteMask & VER_SUITE_DATACENTER)      str += _T("Datacenter Server");
            else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) str += _T("Advanced Server");
            else                                            str += _T("Server");
         }
      }

	  // Include service pack (if any)
	  if(_tcslen(osvi.szCSDVersion)>0){
		  str += _T(" ");
		  str += osvi.szCSDVersion;
      }


	  // Add build number
	  sss.Format(_T(" (build %d)"), osvi.dwBuildNumber);
	  str += sss;
   }
   else str = _T("Pre Windows 2000");

	return str;
}
